package top.lyc829.iot_server.utils;

import org.eclipse.paho.client.mqttv3.*;
import org.eclipse.paho.client.mqttv3.persist.MemoryPersistence;

import java.util.HashMap;
import java.util.Map;

public class MqttUtil {

    private final static String IP = "tcp://192.168.0.109:1883";
    private final static String USER_ID = "IOT_SERVER";

    private static MqttUtil instance = null;

    private MemoryPersistence memoryPersistence;
    private MqttConnectOptions mqttConnectOptions;
    private MqttClient mqttClient;
    private Map<String, Callable> callbackMap;

    private class MqttCallbackHandle implements MqttCallback{

        @Override
        public void connectionLost(Throwable throwable) {

        }

        @Override
        public void messageArrived(String s, MqttMessage mqttMessage) throws Exception {
            Callable callable = callbackMap.get(s);
            if (callable != null){
                callable.callback(mqttMessage);
            }
        }

        @Override
        public void deliveryComplete(IMqttDeliveryToken iMqttDeliveryToken) {

        }
    }

    public interface Callable{
        void callback(MqttMessage mqttMessage);
    }

    private MqttUtil(String ip,String userId){
        try {
            callbackMap = new HashMap<>();
            memoryPersistence = new MemoryPersistence();
            mqttClient = new MqttClient(ip,userId,memoryPersistence);
            mqttConnectOptions = new MqttConnectOptions();
            mqttConnectOptions.setUserName("IOT_SERVER");
            mqttConnectOptions.setCleanSession(true);
            mqttClient.setCallback(new MqttCallbackHandle());
            mqttClient.connect(mqttConnectOptions);
        } catch (MqttException e) {
            e.printStackTrace();
        }
    }

    private void setSubscribeArray(){
        String[] topics = callbackMap.keySet().toArray(new String[0]);
        try {
            mqttClient.subscribe(topics);
        } catch (MqttException e) {
            e.printStackTrace();
        }
    }

    public static MqttUtil build(){
        if (instance == null){
            instance = new MqttUtil(IP,USER_ID);
        }
        return instance;
    }

    public static MqttUtil build(String ip,String userId){
        if (instance == null){
            instance = new MqttUtil(ip,userId);
        }
        return instance;
    }

    public void subscribe(String topic,Callable callable){
        callbackMap.put(topic,callable);
        setSubscribeArray();
    }

    public void publish(String topic,String content){
        MqttMessage mqttMessage = new MqttMessage(content.getBytes());
        mqttMessage.setQos(2);
        try {
            mqttClient.publish(topic,mqttMessage);
        } catch (MqttException e) {
            e.printStackTrace();
        }
    }
}
